﻿#include "common.h"
#include "NedAllocatorImpl.h"
#include "fastlz.h"

wxString GB2312ToUTF8(const wxString& gb2312Text)
{
    wxCSConv gb2312Conv(wxFONTENCODING_CP936);
    return wxString(gb2312Text.wc_str(gb2312Conv), wxConvUTF8);
}

wxString UTF8ToGB2312(const wxString& utf8Text)
{
    wxCSConv gb2312Conv(wxFONTENCODING_CP936);
    return wxString(utf8Text.wc_str(wxConvUTF8), gb2312Conv);
}

// 计算两点角度（0°~360°，以 P1 为原点，P2 为终点）
double CalculateAngle(const wxPoint& p1, const wxPoint& p2)
{
    // 计算坐标差值
    int dx = p2.x - p1.x;
    int dy = p2.y - p1.y;

    // 使用 atan2 计算弧度（调整 dy 符号以适配数学坐标系）
    double radians = std::atan2(-dy, dx);

    // 转换为角度并修正为 0~360°
    double degrees = radians * 180.0 / M_PI;
    if (degrees < 0) {
        degrees += 360.0;
    }

    return degrees;
}

wxArrayString SplitString(const wxString& s, const wxString& delimiter)
{
    wxArrayString arr;
    //wxStringTokenizer tokenizer(s, delimiter);
    //while (tokenizer.HasMoreTokens()) {
    //    arr.Add(tokenizer.GetNextToken());
    //}
    return arr;
}

bool ReadFileToMemoryBuffer(const wxString& filePath, wxMemoryBuffer& buffer)
{
    wxFile file;
    if (!file.Open(filePath, wxFile::read))
    {
        return false;
    }

    // 获取文件大小
    const wxFileOffset fileSize = file.Length();
    if (fileSize == wxInvalidOffset)
    {
        file.Close();
        return false;
    }

    char *tmpBuffer = (char*)allocBytes(fileSize);

    // 读取文件内容
    ssize_t bytesRead = file.Read(tmpBuffer, fileSize);
    if (bytesRead != fileSize)
    {
        deallocBytes(tmpBuffer);
        file.Close();
        return false;
    }

    buffer.AppendData(tmpBuffer, fileSize);

    deallocBytes(tmpBuffer);
    file.Close();
    return true;
}

// 递归删除目录下的所有文件和子目录
bool DeleteDirectoryRecursive(const wxString& dirPath)
{
    if (!wxDir::Exists(dirPath)) {
        return false;
    }

    wxDir dir(dirPath);
    wxString filename;

    // 先删除所有文件
    bool hasFiles = dir.GetFirst(&filename, wxEmptyString, wxDIR_FILES);
    while (hasFiles) {
        wxString filePath = dirPath + wxFileName::GetPathSeparator() + filename;
        if (!wxRemoveFile(filePath)) {
            return false;
        }
        hasFiles = dir.GetNext(&filename);
    }

    // 递归删除所有子目录
    bool hasSubDirs = dir.GetFirst(&filename, wxEmptyString, wxDIR_DIRS);
    while (hasSubDirs) {
        wxString subDirPath = dirPath + wxFileName::GetPathSeparator() + filename;
        if (!DeleteDirectoryRecursive(subDirPath)) {  // 递归调用
            return false;
        }
        hasSubDirs = dir.GetNext(&filename);
    }

    // 最后删除当前空目录
    if (!wxFileName::Rmdir(dirPath)) {
        return false;
    }

    return true;
}

// 删除指定目录下的所有文件（不递归删除子目录）
bool DeleteAllFilesInDir(const wxString& dirPath,std::vector<wxString> files)
{
    if (!wxDir::Exists(dirPath)) {
        return false;
    }

    wxDir dir(dirPath);
    wxString filename;

    bool success = true;
    bool cont = dir.GetFirst(&filename, wxEmptyString, wxDIR_FILES); // 只获取文件，不包含子目录

    while (cont) {
        wxString fullPath = dirPath + wxFileName::GetPathSeparator() + filename;

        auto it = std::find_if(files.begin(), files.end(), [filename](const wxString& str) {
            return filename.Contains(str); // wxString::Contains 方法
        });

        if (it == files.end()) {
            if (!wxRemoveFile(fullPath)) {
                success = false;
            }
        }

        cont = dir.GetNext(&filename);
    }

    return success;
}

bool ListFilesInDirectory(const wxString& dirPath,wxVector<wxString>& decPaths)
{
    wxDir dir(dirPath);

    if (!dir.IsOpened()) {
        return false;
    }

    wxString filename;
    bool cont = dir.GetFirst(&filename); // 获取第一个文件/文件夹

    while (cont) {
        wxString fullPath = dirPath + wxFileName::GetPathSeparator() + filename;

        if (wxFileName::DirExists(fullPath)) {
            // 如果是文件夹，递归遍历
            ListFilesInDirectory(fullPath,decPaths);
        } else {
            // 如果是文件，输出完整路径
            decPaths.push_back(fullPath);
        }

        cont = dir.GetNext(&filename); // 获取下一个文件/文件夹
    }

    return true;
}

// 压缩数据（使用 FastLZ）
wxMemoryBuffer CompressWithFastLZ(const void* data, size_t dataLen) {
    // FastLZ 需要的最大压缩后大小
    size_t maxCompressedLen = dataLen + (dataLen * 0.05) + 16; // 预估压缩后大小

    wxMemoryBuffer buffer(maxCompressedLen);
    int compressedLen = fastlz_compress(
        data,             // 输入数据
        dataLen,          // 输入数据长度
        buffer.GetData()  // 输出缓冲区
        );

    if (compressedLen <= 0) {
        wxLogError("FastLZ compression failed!");
        return wxMemoryBuffer(); // 返回空缓冲区表示失败
    }

    buffer.SetDataLen(compressedLen); // 设置实际压缩后长度
    return buffer;
}

wxMemoryBuffer DecompressWithFastLZ(const void* compressedData, size_t compressedLen, size_t originalLen) {
    wxMemoryBuffer buffer(originalLen);
    int decompressedLen = fastlz_decompress(
        compressedData,   // 压缩数据
        compressedLen,    // 压缩数据长度
        buffer.GetData(), // 解压输出缓冲区
        originalLen       // 原始数据长度（必须已知）
        );

    if (decompressedLen != (int)originalLen) {
        wxLogError("FastLZ decompression failed! Expected %zu, got %d", originalLen, decompressedLen);
        return wxMemoryBuffer(); // 返回空缓冲区表示失败
    }

    buffer.SetDataLen(decompressedLen);
    return buffer;
}

wxUint16 qChecksum(const char* data, size_t len)
{
    wxUint16 crc = 0;
    for (size_t i = 0; i < len; i++) {
        crc ^= (wxUint16)(data[i]) << 8;
        for (int j = 0; j < 8; j++) {
            if (crc & 0x8000)
                crc = (crc << 1) ^ 0x1021; // CRC-16-CCITT 多项式
            else
                crc <<= 1;
        }
    }
    return crc;
}

void RemoveDataFromMemoryBuffer(wxMemoryBuffer& buffer,size_t pos, size_t len)
{
    if (pos < 0 || pos >= buffer.GetDataLen() || len == 0)
        return;

    size_t remainingBytes = buffer.GetDataLen() - pos - len;
    if (remainingBytes > 0) {
        void* dest = static_cast<char*>(buffer.GetData()) + pos;
        const void* src = static_cast<char*>(buffer.GetData()) + pos + len;
        memmove(dest, src, remainingBytes);
    }

    buffer.SetDataLen(buffer.GetDataLen() - len); // 调整缓冲区大小
}

